/*******************************************************************************
*  file    : testutils.cpp
*  created : 25.06.2014
*  author  : Slyshyk Oleksiy (alexSlyshyk@gmail.com)
*******************************************************************************/

#include "testutils.hpp"
#include <QPluginLoader>
#include <QDebug>
#include <QDir>
#include <QCoreApplication>
#include <cstdio>

#include <utils.hpp>
#include <dataobject.hpp>

TestUtils::TestUtils(QObject *parent) :
    QObject(parent)
{
    loadPlugins();
}

void TestUtils::startTests()
{
    test_linearization();
    test_func_linearization();

    test_save_load_object_interface();

    emit endAllTests();
}

void TestUtils::loadPlugins()
{
    QDir pluginsDir = QDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files))
        {
            QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
            QObject *plugin = loader.instance();
            if (plugin)
                {
                    populatePlugins(plugin);
                }
        }
}

void TestUtils::populatePlugins(QObject *plugin)
{
    if(plugin)
        {
            SaveLoadObjectInterface* iSaveFormat = qobject_cast<SaveLoadObjectInterface *>(plugin);
            if(iSaveFormat)
                {
                    saveFormatPlugins_[iSaveFormat->name()] = iSaveFormat;
                    qDebug() << QStringLiteral("Загружен плагин ") + iSaveFormat->name();
                }
        }
}

bool TestUtils::test_linearization()
{
    qDebug() << Q_FUNC_INFO;

    double y = plugin_utils::linear_smooth(0.,0.,2.,2.,1.);

    qDebug() << "Wait 1.0, receive " << y;
    if( std::abs(y - 1.0) > 0.000001 )
        return false;

    y = plugin_utils::linear_smooth(0.,0.,-2.,2., 1.);
    qDebug() << "Wait -1.0, receive " << y;
    if( std::abs(y + 1.0) > 0.000001 )
        return false;

    y = plugin_utils::linear_smooth(0.,0.,-2.,2., -1.);
    qDebug() << "Wait 1.0, receive " << y;
    if( std::abs(y - 1.0) > 0.000001 )
        return false;

    return true;
}

bool TestUtils::test_func_linearization()
{
    qDebug() << Q_FUNC_INFO;
    QVector<std::complex<double> > data,res,need;

    data = {0.,1.,2.,1.,0.};

    double start_t = 0.000000000;
    double dt_data = 4.0;
    double dt      = 1.0;
    res.reserve(20);
    for(int i = 0; i < 16; ++i)
        {
            double y = plugin_utils::get_func_value_linear(data,start_t,dt_data,i*dt);
            res.append( std::complex<double>(i*dt,y) );
        }

    printf("res : \r\n");
    for(const auto& v : res)
        printf("[%f,%f] \r\n", v.real(), v.imag());
    printf("\r\n");



    return true;
}

bool TestUtils::test_save_load_object_interface()
{
    if(saveFormatPlugins_.keys().contains("object_json"))
        {
            SaveLoadObjectInterface* iFace = saveFormatPlugins_["object_json"];
            DataObject* tst_data_obj = new DataObject;
            std::vector<std::complex<double>> data;
            data.reserve(10000);
            for(int i = 0 ; i < 10000 ; ++i)
                data.push_back( i / 10.0 );
            tst_data_obj->setDataL(data);
            tst_data_obj->setDataR(data);
            tst_data_obj->setSampleRate(100500);
            tst_data_obj->setDescription("Tata tatat.\r\n Second string \n");
            tst_data_obj->setObjectName("Test data object");

            if(iFace)
                iFace->saveObjectToFile("test_data_object.json", tst_data_obj);

            DataObject* tst_data_obj1 = dynamic_cast<DataObject*>(iFace->loadObjectFromFile("test_data_object.json")) ;

            if(tst_data_obj1)
                {
                    qDebug() << "Read data object " << tst_data_obj1->objectName();
                    qDebug() << tst_data_obj1->description();
                    qDebug() << tst_data_obj1->sampleRate();
                    qDebug() << tst_data_obj1->time();
                    qDebug() << tst_data_obj1->dataL();
                    qDebug() << tst_data_obj1->dataR();
                }


        }

    return true;
}
